package log

import (
	"fmt"
	"gitee.com/MrDaiM/msgo/internal/msstrings"
	"io"
	"log"
	"os"
	"path"
	"strings"
	"time"
)

const (
	greenBg   = "\033[97;42m"
	whiteBg   = "\033[90;47m"
	yellowBg  = "\033[90;43m"
	redBg     = "\033[97;41m"
	blueBg    = "\033[97;44m"
	magentaBg = "\033[97;45m"
	cyanBg    = "\033[97;46m"
	green     = "\033[32m"
	white     = "\033[37m"
	yellow    = "\033[33m"
	red       = "\033[31m"
	blue      = "\033[34m"
	magenta   = "\033[35m"
	cyan      = "\033[36m"
	reset     = "\033[0m"
)

type LoggerLevel int

const (
	LevelDebug LoggerLevel = iota // debug, 三者的日志都会打印
	LevelInfo                     // 如果是info级别 debug 级别的日志不会打印
	LevelError                    // 如果是error级别 只会打印error日志
)

func (level LoggerLevel) Level() string {
	switch level {
	case LevelDebug:
		return "DEBUG"
	case LevelInfo:
		return "INFO"
	case LevelError:
		return "ERROR"
	default:
		return ""
	}
}

type LoggerWriter struct { //将日志等级和输出writer 进行绑定
	Level LoggerLevel
	Out   io.Writer
}

type Logger struct {
	Formatter LoggingFormatter
	//Outs         []io.Writer
	Outs         []*LoggerWriter
	Level        LoggerLevel
	LoggerFields Fields
	LogPath      string
	LogFileSize  int64 // 文件存储大小设置
}

func New() *Logger {
	return &Logger{}
}

func Default() *Logger {
	logger := New()
	w := &LoggerWriter{
		Level: LevelDebug,
		Out:   os.Stdout,
	}
	logger.Outs = append(logger.Outs, w)
	logger.Level = LevelDebug
	logger.Formatter = &TextFormatter{}
	return logger
}

func (l *Logger) WithFields(fields Fields) *Logger {
	// 防止其log 都有会输出fields 这里重新构建一个logger对象
	return &Logger{
		Formatter:    l.Formatter,
		Outs:         l.Outs,
		Level:        l.Level,
		LoggerFields: fields,
	}
}

func (l *Logger) Info(msg any) {
	l.Print(LevelInfo, msg)
}

func (l *Logger) Debug(msg any) {
	l.Print(LevelDebug, msg)
}

func (l *Logger) Error(msg any) {
	l.Print(LevelError, msg)
}

func (l *Logger) Print(level LoggerLevel, msg any) {
	if l.Level > level {
		// 级别不满足， 不打印日志
		return
	}
	param := &LoggingFormatParam{
		Level:        level,
		LoggerFields: l.LoggerFields,
		Msg:          msg,
	}

	formatter := l.Formatter.Format(param)
	// 将格式化好的 日志果格式输入到不同的标准输出中
	for _, out := range l.Outs {
		if out.Out == os.Stdout { // 终端携带颜色
			param.Color = true
			formatter = l.Formatter.Format(param)
			_, _ = fmt.Fprintf(out.Out, formatter)
		}
		if out.Level == -1 || level == out.Level {
			_, _ = fmt.Fprintf(out.Out, formatter)
			// 检测日志大小自动切分
			l.CheckFileSize(out)

		}

	}
}

func (l *Logger) CheckFileSize(w *LoggerWriter) {
	// 判断对应的文件大小
	logFile := w.Out.(*os.File)
	if logFile != nil {
		stat, err := logFile.Stat()
		if err != nil {
			log.Println(err)
			return
		}
		size := stat.Size()
		if l.LogFileSize <= 0 { // 如果外界没有设置，这里设置一个默认的最大大小
			l.LogFileSize = 100 << 20 // 1024 * 1024 // 大小为100M
		}
		if size >= l.LogFileSize {
			// 获取文件的名称
			_, name := path.Split(stat.Name())
			fileName := name[0:strings.Index(name, ".")]
			writer := FileWriter(path.Join(l.LogPath, msstrings.JoinStrings(fileName, ".", time.Now().UnixMilli(), ".log")))
			// 替换原有的 out
			w.Out = writer
		}

	}

}

func (l *Logger) SetLogPath(logPath string) {
	l.LogPath = logPath
	l.Outs = append(l.Outs, &LoggerWriter{
		Level: -1,
		Out:   FileWriter(path.Join(logPath, "all.log")),
	})
	l.Outs = append(l.Outs, &LoggerWriter{
		Level: LevelDebug,
		Out:   FileWriter(path.Join(logPath, "debug.log")),
	})
	l.Outs = append(l.Outs, &LoggerWriter{
		Level: LevelInfo,
		Out:   FileWriter(path.Join(logPath, "info.log")),
	})
	l.Outs = append(l.Outs, &LoggerWriter{
		Level: LevelError,
		Out:   FileWriter(path.Join(logPath, "error.log")),
	})
}

func FileWriter(name string) io.Writer {
	w, err := os.OpenFile(name, os.O_WRONLY|os.O_CREATE|os.O_APPEND, 0644)
	if err != nil {
		panic(err)
	}
	return w
}
